package com.sailors.common.task.provider.infra.system.exceptions;

import com.sailors.common.task.provider.infra.design.common.exception.BussinessException;
import com.sailors.common.task.provider.infra.design.common.rest.BaseResponse;
import com.sailors.common.task.provider.infra.design.common.rest.Bru;
import com.sailors.common.task.provider.infra.design.common.rest.ReturnCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

@Slf4j
@RestControllerAdvice
public class ExceptionHandlers {

	@ExceptionHandler
	public BaseResponse<Object> exceptionHandler(Exception exception) {
		log.error("未知系统异常: {}", exception.toString(), exception);
		return Bru.ofEnum(ReturnCode.SERVER_INTERNAL_ERROR);
	}

	@ExceptionHandler(BussinessException.class)
	public BaseResponse<Object> bussinessException(BussinessException e) {
		log.error("业务异常: {}", e.toString(), e);
		return Bru.ofMsg(e.getMessage());
	}

	@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
	public BaseResponse<Object> httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
		log.error("请求方法不被支持: {}", e.toString(), e);
		return Bru.ofEnum(ReturnCode.REQUEST_METHOD_NOT_SUPPORTED);
	}

	@ExceptionHandler(DuplicateKeyException.class)
	public BaseResponse<Object> duplicateKeyException(DuplicateKeyException e) throws Exception {
		log.error("数据重复: {}", e.toString(), e);
		return Bru.ofEnum(ReturnCode.DATA_DUPLICATION);
	}

	@ExceptionHandler(HttpMessageNotReadableException.class)
	public BaseResponse<Object> httpMessageNotReadableException(HttpMessageNotReadableException e) {
		log.error("错误的请求体: {}", e.toString(), e);
		return Bru.ofEnum(ReturnCode.BAD_REQUEST_BODY);
	}

	@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
	public BaseResponse<Object> httpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
		log.error("不支持的请求体类型: {}", e.toString(), e);
		return Bru.ofEnum(ReturnCode.BAD_REQUEST_BODY);
	}

	@ExceptionHandler(MissingServletRequestParameterException.class)
	public BaseResponse<Object> missingServletRequestParameterException(MissingServletRequestParameterException e) throws Exception {
		log.error("请求参数不正确: {}", e.toString(), e);
		return Bru.ofEnum(ReturnCode.MISSING_REQUEST_PARAMETER);
	}

	@ExceptionHandler(BindException.class)
	public BaseResponse<Object> bindException(BindException e) throws Exception {
		log.error("参数绑定错误: {}", e.toString());
		List<FieldError> fieldErrors = e.getFieldErrors();
		return parameterVerificationFails(fieldErrors);
	}

	@ExceptionHandler(MethodArgumentNotValidException.class)
	public BaseResponse<Object> illegalParamsExceptionHandler(MethodArgumentNotValidException e) {
		log.error("参数校验失败: {}", e.toString());
		List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
		return parameterVerificationFails(fieldErrors);
	}

	/**
	 * 参数校验失败
	 * @param fieldErrors 错误参数
	 * @return 返回结果
	 */
	private BaseResponse<Object> parameterVerificationFails(List<FieldError> fieldErrors) {
		if (CollectionUtils.isEmpty(fieldErrors)) {
			return Bru.ofEnum(ReturnCode.PARAMETER_VERIFICATION_FAILS);
		}
		//占位符不支持动态，所以取第一个
		FieldError fieldError = fieldErrors.get(0);
		return Bru.error(fieldError);
	}

}
